# -*- coding:utf-8 -*-
import requests
import threading
import time
import re
import os
import sys
import pandas as pd
import json
from urllib.parse import quote
import execjs

def get_secret(host):
    path = os.path.join('.', 'js', 'generatetoken.js')
    with open(path, 'r', encoding='utf-8') as f:
        source = f.read()
        exec = execjs.compile(source)
        key = exec.call('generateHostKey', host)
        randomNum = exec.call('getRandomNum', key)
        # timeStamp = int(round(time.time() * 1000))
        timeStamp = exec.call('getTimeStamp')
        secretkey = exec.call('generateHostMD5Key', key, timeStamp)
        return {
            "host": host,
            "rd": randomNum,
            "ts": timeStamp,
            "secretkey" : secretkey,
            "identify" : '0',
        }

def show_host():
    host_list = []
    host_path = "C:\Windows\System32\drivers\etc\hosts"
    host_file = open(host_path, "r", encoding="utf-8")
    while 1:
        line = host_file.readline()
        if not line:
            break
        host_list.append(line)
    host_file.close()
    return host_list


def host_write(host_list, ip, host_name):
    host_path = "C:\Windows\System32\drivers\etc\hosts"
    host_file = open(host_path, "w",  encoding="utf-8")
    write = 0
    content = ""
    for line in range(len(host_list)):
        if (host_list[line][0] != "#" and host_name in host_list[line]):
            host_list[line] = ip + ' ' + host_name + '\n'
            write = 1
    if (write == 0):
        host_list.append(ip + ' ' + host_name + '\n')
    for line in host_list:
        content += line
    host_file.write(content)
    host_file.close()

# 获取最优Host类
class BestHost:
    def __init__(self, host_name) -> None:
        self.host_name = host_name
        self.threads = []
        self.threadLock = threading.Lock()
        self.fastest_ip = None
        self.ms = 9999

    def get_cdn_list(self):
        headers = {
            'content-type': 'application/json',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54',
            'cookie': 'qHistory=Ly9waW5nLmNoaW5hei5jb20vZ2l0aHViLmNvbV9waW5n5qOA5rWL; toolbox_urls=%s; pinghost=%s' % (self.host_name, self.host_name),
        }

        data = quote('host=%s&linetype=电信,多线,联通,移动,其他' % self.host_name)
        r = requests.post('http://ping.chinaz.com/' + self.host_name,
                        headers=headers, data=data)
        pattern_id_token = re.compile(
            r'<div class="row listw tc clearfix" id="(.+?)" linetype.*token="(.*?)"')
        pattern_name = re.compile(r'serveruroup="(.*)" company=".*">(.*)</div>')
        df1 = pd.DataFrame(pattern_id_token.findall(
            r.text, re.M), columns=['id', 'token'])
        df2 = pd.DataFrame(
            pattern_name.findall(r.text, re.M), columns=['uroup', 'name'])
        self.cdn_list = pd.concat([df1, df2], axis=1)
        self.cdn_list['tTL'] = None
        self.cdn_list['timeMs'] = None
        self.cdn_list['address'] = None
        self.cdn_list['ipAddress'] = None
        print(self.cdn_list)
        return self.cdn_list


    def ping_check(self, cdn_data):
        url = 'https://ping.chinaz.com/pingcheck'
        headers = {
            'content-type': 'application/json',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54',
            'cookie': 'qHistory=Ly9waW5nLmNoaW5hei5jb20vZ2l0aHViLmNvbV9waW5n5qOA5rWL; toolbox_urls=%s; pinghost=%s' % (self.host_name, self.host_name),
            'referer': 'https://ping.chinaz.com/%s' % self.host_name
        }

        data = get_secret(self.host_name)
        data["guid"] = cdn_data['id']
        data["token"] = cdn_data['token']
        html = requests.post(url=url, headers=headers, data=json.dumps(data))
        if html.status_code == 200:
            json_text = json.loads(html.text)
            if not json_text is None and 'data' in json_text:
                json_data = json_text['data']

                cdn_data['tTL'] = json_data['tTL']
                cdn_data['timeMs'] = json_data['timeMs']
                cdn_data['address'] = json_data['address']
                cdn_data['ipAddress'] = json_data['ipAddress']
                print(cdn_data, json_data)
                print(type(cdn_data))
                return json_data


    def update_fast(self, cdn_data):
        ping_result = self.ping_check(cdn_data)
        if not ping_result:
            return
        self.threadLock.acquire()
        print(ping_result)
        if 'timeMs' in ping_result:
            if ping_result['timeMs'].isdigit():
                if int(ping_result['timeMs']) < self.ms:
                    self.ms = int(int(ping_result['timeMs']))
                    self.fastest_ip = ping_result['address']
            elif ping_result['timeMs'] == '<1':
                self.ms = 0.1
                self.fastest_ip = ping_result['address']
        self.threadLock.release()

    def run(self):
        self.get_cdn_list()
        for _, data in self.cdn_list.iterrows():
            t = threading.Thread(target=BestHost.update_fast, args=(self, data))
            t.start()
            self.threads.append(t)

        for ths in self.threads:
            ths.join()

        self.cdn_list.to_csv('cdn_list_result.csv')
        print(self.cdn_list)
        print('the fastest_ip is ', self.fastest_ip, self.ms)


    def get_fastest_ip(self):
        return self.fastest_ip

if __name__ == '__main__':

    if (len(sys.argv) < 2):
        host_name = "api.themoviedb.org"
        # host_name = "github.com"
    if (len(sys.argv) == 2):
        host_name = sys.argv[1]

    bh = BestHost(host_name)
    bh.run()
    # host_list = show_host()
    # host_write(host_list, Get_info.fastest_ip, host_name)
    # print('set host done!')
